import * as THREE from 'three';
import TWEEN from "three/examples/jsm/libs/tween.module.js"

interface TargetPosition {
  x: number;
  y: number;
  z: number;
}

export default class ModelAnimator {
  private scene: THREE.Scene;
  private model: THREE.Object3D | THREE.Object3D[];
  private animationType: 'split' | 'merge';
  private speed: number;
  private splitDistance: number;

  private meshes: THREE.Mesh[];

  constructor(scene: THREE.Scene, model: THREE.Object3D | THREE.Object3D[], animationType: 'split' | 'merge', speed: number, splitDistance?: number) {
    this.scene = scene;
    this.model = model;
    this.animationType = animationType;
    this.speed = speed;
    this.splitDistance = splitDistance || 0;
    this.meshes = this.extractMeshes(model);
  }

  private extractMeshes(model: THREE.Object3D | THREE.Object3D[]): THREE.Mesh[] {
    let meshes: THREE.Mesh[];
    if (Array.isArray(model)) {
      meshes = model as THREE.Mesh[];
    } else if ((model as THREE.Group).type === 'Group') {
      meshes = (model as THREE.Group).children.filter(child => child.isMesh) as THREE.Mesh[];
    } else if ((model as THREE.Mesh).isMesh) {
      meshes = [model as THREE.Mesh];
    }
    return meshes;
  }

  private calculateTargetPositions(splitDistance: number): TargetPosition[] {
    // 根据实际需求计算每个网格的目标位置
    // 这里仅做示例，假设我们沿X轴均匀分布
    return this.meshes.map((mesh, index) => ({
      x: mesh.position.x + splitDistance * (index - (this.meshes.length - 1) / 2),
      y: mesh.position.y,
      z: mesh.position.z,
    }));
  }

  public animateSplit(): void {
    const targetPositions = this.calculateTargetPositions(this.splitDistance);
    this.animateMeshes(targetPositions);
  }

  public animateMerge(): void {
    const originalPositions = this.meshes.map(mesh => ({
      x: mesh.position.x,
      y: mesh.position.y,
      z: mesh.position.z,
    }));
    this.animateMeshes(originalPositions);
  }

  private animateMeshes(targetPositions: TargetPosition[]): void {
    this.meshes.forEach((mesh, index) => {
      const currentPosition: TargetPosition = {
        x: mesh.position.x,
        y: mesh.position.y,
        z: mesh.position.z,
      };
      new TWEEN.Tween(currentPosition)
        .to(targetPositions[index], this.speed)
        .easing(TWEEN.Easing.Quadratic.Out)
        .onUpdate(() => {
          mesh.position.set(currentPosition.x, currentPosition.y, currentPosition.z);
        })
        .start();
    });

    // 确保最后一个动画结束后再执行下一个动作
    TWEEN.update();
  }

  public startAnimation(): void {
    if (this.animationType === 'split') {
      this.animateSplit();
    } else if (this.animationType === 'merge') {
      this.animateMerge();
    }
  }

  // 使用示例
  static createAndAnimate(scene: THREE.Scene, model: THREE.Object3D | THREE.Object3D[], animationType: 'split' | 'merge', speed: number, splitDistance?: number): void {
    const animator = new ModelAnimator(scene, model, animationType, speed, splitDistance);
    animator.startAnimation();
  }
}

// // 使用示例：
// const scene = new THREE.Scene();
// const model = ... // 初始化模型
// ModelAnimator.createAndAnimate(scene, model, 'split', 1000, 5); // 分解动画，速度1秒，拆分距离5单位